package com.capgemini.fs.presentation.forum.web.action;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.actions.DispatchAction;

import com.capgemini.fs.app.ekms.model.Topic;
import com.capgemini.fs.app.ekms.persistence.util.QueryHelper;
import com.capgemini.fs.app.ekms.service.ForumService;
import com.capgemini.fs.app.ekms.service.TopicService;
import com.capgemini.fs.app.ekms.service.util.data.TopicInfo;
import com.capgemini.fs.presentation.forum.web.form.ShowForumDetailsForm;

public class ShowForumDetailsAction extends DispatchAction {

	private TopicService topicService = null;
	private ForumService forumService=null;
	private int pageSize = 10;

	public ForumService getForumService() {
		return forumService;
	}

	public void setForumService(ForumService forumService) {
		this.forumService = forumService;
	}

	public TopicService getTopicService() {
		return topicService;
	}

	public void setTopicService(TopicService topicService) {
		this.topicService = topicService;
	}

	// Sort Topic Info list
	public List<TopicInfo> sortTopicInfoList(String sortType, String sortOrder,
			List<TopicInfo> list) {

		// Compare Topic By Topic subject
		Comparator<TopicInfo> compareByTopicSubject = new Comparator<TopicInfo>() {
			public int compare(TopicInfo t1, TopicInfo t2) {
				return t1.getSubject().compareTo(t2.getSubject());
			}
		};

		// Compare Topic By Topic Status
		Comparator<TopicInfo> compareByTopicStatus = new Comparator<TopicInfo>() {
			public int compare(TopicInfo t1, TopicInfo t2) {
				if (!QueryHelper.isNullOrEmpty(t1.getStatus())
						&& !QueryHelper.isNullOrEmpty(t2.getStatus())) {
					if (t1.getStatus() < t2.getStatus()) {
						return -1;
					}
					if (t1.getStatus() > t2.getStatus()) {
						return 1;
					}
				}
				return 0;
			}
		};

//		// Compare Topic by Topic last update time
//		Comparator<TopicInfo> compareByLastUpdateTime = new Comparator<TopicInfo>() {
//			public int compare(TopicInfo t1, TopicInfo t2) {
//				return t1.getLastUpdateDate().compareTo(t2.getLastUpdateDate());
//			}
//		};

		// Compare topic by replies count
		Comparator<TopicInfo> compareByRepliesCount = new Comparator<TopicInfo>() {
			public int compare(TopicInfo t1, TopicInfo t2) {
				return t1.getRepliesCount().compareTo(t2.getRepliesCount());
			}
		};

		// Compare topic by views count
		Comparator<TopicInfo> compareByViewsCount = new Comparator<TopicInfo>() {
			public int compare(TopicInfo t1, TopicInfo t2) {
				return t1.getViewsCount().compareTo(t2.getViewsCount());
			}
		};

		// Compare topic by last post time
		Comparator<TopicInfo> compareByLastPostTime = new Comparator<TopicInfo>() {
			public int compare(TopicInfo t1, TopicInfo t2) {
				if (null == t1.getLastPost() && null == t2.getLastPost()) {
					return 0;
				}
				if (null == t1.getLastPost() && null != t2.getLastPost()) {
					return -1;
				}
				if (null != t1.getLastPost() && null == t2.getLastPost()) {
					return 1;
				} else {
					return t1.getLastPost().getCreateDate().compareTo(
							t2.getLastPost().getCreateDate());
				}

			}
		};
		if (null == sortType) {
			Collections.sort(list, compareByLastPostTime);
			if ("desc".equals(sortOrder)) {
				Collections.reverse(list);
			}
		}
		if ("subject".equals(sortType)) {
			Collections.sort(list, compareByTopicSubject);
			if ("desc".equals(sortOrder)) {
				Collections.reverse(list);
			}
		}
		if ("status".equals(sortType)) {
			Collections.sort(list, compareByTopicStatus);
			if ("desc".equals(sortOrder)) {
				Collections.reverse(list);
			}
		}
		if ("lastPostTime".equals(sortType)) {
			Collections.sort(list,compareByLastPostTime);
			if ("desc".equals(sortOrder)) {
				Collections.reverse(list);
			}
		}
		if ("repliesCount".equals(sortType)) {
			Collections.sort(list, compareByRepliesCount);
			if ("desc".equals(sortOrder)) {
				Collections.reverse(list);
			}
		}
		if ("viewsCount".equals(sortType)) {
			Collections.sort(list, compareByViewsCount);
			if ("desc".equals(sortOrder)) {
				Collections.reverse(list);
			}
		}
		return list;
	}

	// List all topics in current forum
	public ActionForward listTopic(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response) {

		int forumId = Integer.valueOf(request.getParameter("forumId"));

		// get query criteria from ActionForm
		String topicSubjectQuery = ((ShowForumDetailsForm) form)
				.getTopicSubjectQuery();
		Integer topicActiveQuery = ((ShowForumDetailsForm) form)
				.getTopicActiveQuery();
		String topicContentQuery = ((ShowForumDetailsForm) form)
				.getTopicContentQuery();
		// get sort parameters(sortType & sortOrder)
		String sortType = ((ShowForumDetailsForm) form).getSortType();
		String sortOrder = ((ShowForumDetailsForm) form).getSortOrder();

		// This list stored all the topics queried from database
		List<Topic> list;
		List<TopicInfo> topicInfoList = new ArrayList<TopicInfo>();
		// if forum status not decided, query forum depending on just forum
		// name.
		if (null == topicActiveQuery || 99 == topicActiveQuery) {
			list = topicService.queryTopic(forumId, topicSubjectQuery, null);
			// Turn Topic to TopicInfo, encapsulate data
			GenerateTopicInfoList(topicInfoList, list);
			topicActiveQuery = 99;
			// else query depending on both forum name and status
		} else {
			list = topicService.queryTopic(forumId, topicSubjectQuery,
					topicActiveQuery);
			GenerateTopicInfoList(topicInfoList, list);
		}

		sortTopicInfoList(sortType, sortOrder, topicInfoList);
		if (null == sortType) {
			sortType = "name";
			sortOrder = "asce";
		}
		// Total row number depends on the topics returned from server
		int totalRows = topicInfoList.size();
		// Initial current page at page 1
		int nowPage = 1;
		// Get page numbers
		int totalPage = getTotalPage(pageSize, totalRows);

		List<TopicInfo> data = new ArrayList<TopicInfo>();

		/**
		 * Add associated topics to current page
		 */
		if (totalRows >= nowPage * pageSize) {
			for (int i = nowPage - 1; i < nowPage * pageSize; i++) {
				data.add(topicInfoList.get(i));
			}
		} else {
			for (int i = nowPage - 1; i < totalRows; i++) {
				data.add(topicInfoList.get(i));
			}
		}
		// Set all the query conditions to request because we still need them on
		// page
		request.setAttribute("forumName",forumService.getForumById(forumId).getName());
		request.setAttribute("topicSubjectQuery", topicSubjectQuery);
		request.setAttribute("topicActiveQuery", topicActiveQuery);
		request.setAttribute("topicContentQuery", topicContentQuery);
		// Paging attributes
		request.setAttribute("sortType", sortType);
		request.setAttribute("sortOrder", sortOrder);
		request.setAttribute("totalPage", nowPage + "/" + totalPage);
		request.setAttribute("nowPage", nowPage);
		// Return forums on current page back
		request.setAttribute("topicInfoList", data);
		request.setAttribute("totalPageNum", totalPage);
		request.setAttribute("statusMap", getStatusMap());
		request.setAttribute("forumId", forumId);
		return mapping.findForward("succ");

	}

	public HashMap<String, String> getStatusMap() {
		HashMap<String, String> map = new HashMap<String, String>();
		map.put("0", "Yes");
		map.put("1", "No");
		return map;
	}

	// Go to Next Page
	public ActionForward goToNextPage(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response) {

		int forumId = Integer.valueOf(request.getParameter("forumId"));
		// get query criteria from ActionForm
		String topicSubjectQuery = ((ShowForumDetailsForm) form)
				.getTopicSubjectQuery();
		Integer topicActiveQuery = ((ShowForumDetailsForm) form)
				.getTopicActiveQuery();
		String topicContentQuery = ((ShowForumDetailsForm) form)
				.getTopicContentQuery();
		// get sort parameters(sortType & sortOrder)
		String sortType = ((ShowForumDetailsForm) form).getSortType();
		String sortOrder = ((ShowForumDetailsForm) form).getSortOrder();

		// This list stored all the topics queried from database
		List<Topic> list;
		List<TopicInfo> topicInfoList = new ArrayList<TopicInfo>();
		// if forum status not decided, query forum depending on just forum
		// name.
		if (null == topicActiveQuery || 99 == topicActiveQuery) {
			list = topicService.queryTopic(forumId, topicSubjectQuery, null);
			// Turn Topic to TopicInfo, encapsulate data
			GenerateTopicInfoList(topicInfoList, list);
			topicActiveQuery = 99;
			// else query depending on both forum name and status
		} else {
			list = topicService.queryTopic(forumId, topicSubjectQuery,
					topicActiveQuery);
			GenerateTopicInfoList(topicInfoList, list);
		}

		sortTopicInfoList(sortType, sortOrder, topicInfoList);
		int totalRows = topicInfoList.size();
		// ///////////////////////////HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
		ShowForumDetailsForm sf = (ShowForumDetailsForm) form;
		int nowPage = sf.getNowPage();
		int totalPage = getTotalPage(pageSize, totalRows);

		List<TopicInfo> data = new ArrayList<TopicInfo>();
		if (totalRows > (nowPage + 1) * pageSize) {
			for (int i = nowPage * pageSize; i < (nowPage + 1) * pageSize; i++) {
				data.add(topicInfoList.get(i));
			}
		} else {
			for (int i = nowPage * pageSize; i < totalRows; i++) {
				data.add(topicInfoList.get(i));
			}
		}
		nowPage = nowPage + 1;
		// Set all the query conditions to request because we still need them on
		// page
		request.setAttribute("forumName",forumService.getForumById(forumId).getName());
		request.setAttribute("topicSubjectQuery", topicSubjectQuery);
		request.setAttribute("topicActiveQuery", topicActiveQuery);
		request.setAttribute("topicContentQuery", topicContentQuery);
		// Paging attributes
		request.setAttribute("sortType", sortType);
		request.setAttribute("sortOrder", sortOrder);
		request.setAttribute("totalPage", nowPage + "/" + totalPage);
		request.setAttribute("nowPage", nowPage);
		// Return forums on current page back
		request.setAttribute("topicInfoList", data);
		request.setAttribute("totalPageNum", totalPage);
		request.setAttribute("statusMap", getStatusMap());
		request.setAttribute("forumId", forumId);
		return mapping.findForward("succ");
	}

	// Go to Previous Page
	public ActionForward goToPreviousPage(ActionMapping mapping,
			ActionForm form, HttpServletRequest request,
			HttpServletResponse response) {
		int forumId = Integer.valueOf(request.getParameter("forumId"));
		// get query criteria from ActionForm
		String topicSubjectQuery = ((ShowForumDetailsForm) form)
				.getTopicSubjectQuery();
		Integer topicActiveQuery = ((ShowForumDetailsForm) form)
				.getTopicActiveQuery();
		String topicContentQuery = ((ShowForumDetailsForm) form)
				.getTopicContentQuery();
		// get sort parameters(sortType & sortOrder)
		String sortType = ((ShowForumDetailsForm) form).getSortType();
		String sortOrder = ((ShowForumDetailsForm) form).getSortOrder();

		// This list stored all the topics queried from database
		List<Topic> list;
		List<TopicInfo> topicInfoList = new ArrayList<TopicInfo>();
		// if forum status not decided, query forum depending on just forum
		// name.
		if (null == topicActiveQuery || 99 == topicActiveQuery) {
			list = topicService.queryTopic(forumId, topicSubjectQuery, null);
			// Turn Topic to TopicInfo, encapsulate data
			GenerateTopicInfoList(topicInfoList, list);
			topicActiveQuery = 99;
			// else query depending on both forum name and status
		} else {
			list = topicService.queryTopic(forumId, topicSubjectQuery,
					topicActiveQuery);
			GenerateTopicInfoList(topicInfoList, list);
		}

		sortTopicInfoList(sortType, sortOrder, topicInfoList);
		int totalRows = topicInfoList.size();
		ShowForumDetailsForm sf = (ShowForumDetailsForm) form;
		int nowPage = sf.getNowPage();
		int totalPage = getTotalPage(pageSize, totalRows);

		List<TopicInfo> data = new ArrayList<TopicInfo>();
		if (nowPage - 2 >= 0) {
			for (int i = (nowPage - 2) * pageSize; i < (nowPage - 1) * pageSize; i++) {
				data.add(topicInfoList.get(i));
			}
		}

		nowPage = nowPage - 1;
		// Set all the query conditions to request because we still need them on
		// page
		request.setAttribute("forumName",forumService.getForumById(forumId).getName());
		request.setAttribute("topicSubjectQuery", topicSubjectQuery);
		request.setAttribute("topicActiveQuery", topicActiveQuery);
		request.setAttribute("topicContentQuery", topicContentQuery);
		// Paging attributes
		request.setAttribute("sortType", sortType);
		request.setAttribute("sortOrder", sortOrder);
		request.setAttribute("totalPage", nowPage + "/" + totalPage);
		request.setAttribute("nowPage", nowPage);
		// Return forums on current page back
		request.setAttribute("topicInfoList", data);
		request.setAttribute("totalPageNum", totalPage);
		request.setAttribute("statusMap", getStatusMap());
		request.setAttribute("forumId", forumId);
		return mapping.findForward("succ");
	}

	// Go to Target Page
	public ActionForward goToTargetPage(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response) {
		int forumId = Integer.valueOf(request.getParameter("forumId"));
		// get query criteria from ActionForm
		String topicSubjectQuery = ((ShowForumDetailsForm) form)
				.getTopicSubjectQuery();
		Integer topicActiveQuery = ((ShowForumDetailsForm) form)
				.getTopicActiveQuery();
		String topicContentQuery = ((ShowForumDetailsForm) form)
				.getTopicContentQuery();
		// get sort parameters(sortType & sortOrder)
		String sortType = ((ShowForumDetailsForm) form).getSortType();
		String sortOrder = ((ShowForumDetailsForm) form).getSortOrder();

		// This list stored all the topics queried from database
		List<Topic> list;
		List<TopicInfo> topicInfoList = new ArrayList<TopicInfo>();
		// if forum status not decided, query forum depending on just forum
		// name.
		if (null == topicActiveQuery || 99 == topicActiveQuery) {
			list = topicService.queryTopic(forumId, topicSubjectQuery, null);
			// Turn Topic to TopicInfo, encapsulate data
			GenerateTopicInfoList(topicInfoList, list);
			topicActiveQuery = 99;
			// else query depending on both forum name and status
		} else {
			list = topicService.queryTopic(forumId, topicSubjectQuery,
					topicActiveQuery);
			GenerateTopicInfoList(topicInfoList, list);
		}

		sortTopicInfoList(sortType, sortOrder, topicInfoList);
		int totalRows = topicInfoList.size();
		ShowForumDetailsForm sf = (ShowForumDetailsForm) form;
		// get target page number from ActionForm
		int nowPage = sf.getTargetPage();
		int totalPage = getTotalPage(pageSize, totalRows);
		List<TopicInfo> data = new ArrayList<TopicInfo>();
		if (nowPage > 0 && nowPage <= totalPage) {
			data = getTargetPageForums(topicInfoList, nowPage, totalRows);
		}

		// Set all the query conditions to request because we still need them on
		// page
		request.setAttribute("forumName",forumService.getForumById(forumId).getName());
		request.setAttribute("topicSubjectQuery", topicSubjectQuery);
		request.setAttribute("topicActiveQuery", topicActiveQuery);
		request.setAttribute("topicContentQuery", topicContentQuery);
		// Paging attributes
		request.setAttribute("sortType", sortType);
		request.setAttribute("sortOrder", sortOrder);
		request.setAttribute("totalPage", nowPage + "/" + totalPage);
		request.setAttribute("nowPage", nowPage);
		// Return forums on current page back
		request.setAttribute("topicInfoList", data);
		request.setAttribute("totalPageNum", totalPage);
		request.setAttribute("statusMap", getStatusMap());
		request.setAttribute("forumId", forumId);
		return mapping.findForward("succ");
	}

	// Get topics on target page, This method is much useful
	public List<TopicInfo> getTargetPageForums(List<TopicInfo> list,
			int targetNum, int totalNum) {
		List<TopicInfo> data = new ArrayList<TopicInfo>();
		if (targetNum * pageSize <= totalNum) {
			for (int i = (targetNum - 1) * pageSize; i < (targetNum * pageSize); i++) {
				data.add(list.get(i));
			}
		} else {
			for (int i = (targetNum - 1) * pageSize; i < totalNum; i++) {
				data.add(list.get(i));
			}
		}
		return data;
	}

	public int getTotalPage(int pageSize, int totalRows) {
		int totalPage;
		if (totalRows % pageSize > 0) {
			totalPage = totalRows / pageSize + 1;
		} else {
			totalPage = totalRows / pageSize;
		}
		return totalPage;
	}

	// Query Forum
	public ActionForward queryForum(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response) {
		int forumId = Integer.valueOf(request.getParameter("forumId"));
		String topicSubjectQuery = ((ShowForumDetailsForm) form)
				.getTopicSubjectQuery();
		Integer topicActiveQuery = ((ShowForumDetailsForm) form)
				.getTopicActiveQuery();
		if (topicActiveQuery == 99) {
			topicActiveQuery = null;
		}
		List<Topic> list = topicService.queryTopic(forumId, topicSubjectQuery,
				topicActiveQuery);
		Collections.sort(list);
		return mapping.findForward("succ");
	}

	// Turn Topic list to TopicInfo list
	public void GenerateTopicInfoList(List<TopicInfo> topicInfoList,
			List<Topic> topicList) {
		for (Topic topic : topicList) {
			TopicInfo topicInfo = new TopicInfo();
			topicInfo.setId(topic.getId());
			topicInfo.setSubject(topic.getSubject());
			topicInfo.setContent(topic.getContent());
			topicInfo.setAuthor(topic.getAuthor());
			topicInfo.setLastPost(topicService.getLastPost(topic));
			topicInfo.setLastUpdateDate(topic.getLastUpdateDate());
			topicInfo.setRepliesCount(topicService.getRepliesCount(topic));
			topicInfo.setStatus(topic.getStatus());
			topicInfo.setViewsCount(topic.getViewsCount());
			topicInfoList.add(topicInfo);
		}
	}

}
